/****************************************************************************
   Copyright 2013 Stacy Doss

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
****************************************************************************/

%{

#include <stdarg.h>
#include <stdio.h>

#include "lparse_shared.h"
#define ____YYSTYPE Node

int yydebug = 1;
int indent  = 0;
char *iden_dum;

static void yyerror (const char *msg);
int yylex (void);

Group* library;

%}

%union {
    int          i;
    float        f;
    char        *s;
    struct DblAttribute   *da;
    struct IntAttribute   *ia;
    struct StrAttribute   *sa;
    struct CmplxAttribute *ca;
    struct DblVector      *dv;
    struct IntVector      *iv;
    struct StrVector      *sv;
    struct GrpMap         *gm;
    struct Group          *grp;
}

%token COLON
%token SEMI
%token LPAREN
%token RPAREN
%token LBRACE
%token RBRACE
%token COMMA
%token BSLASH
%token <s> IDENT
%token <s> NAME
%token <i> INT
%token <f> FLOAT
%token <s> QSTRING

%type <da>  float_attribute
%type <ia>  int_attribute
%type <sa>  string_attribute
%type <ca>  cplx_attribute
%type <sv>  string_list
%type <gm>  groupitems
%type <grp> group

%% /* Grammar rules and actions follow */
group:    NAME LPAREN  RPAREN  LBRACE  groupitems RBRACE { 
            Group  *g  = new Group($1, "");
            GrpMap *gm = $5;

            g->add(gm);

	    std::map<std::string, std::string>::iterator sab = gm->sa->begin();
	    std::map<std::string, std::string>::iterator sae = gm->sa->end();
	    while (sab != sae) {
	      std::pair<std::string, std::string> p = (*sab);
	      //printf("   sa %s = %s\n", p.first.c_str(), p.second.c_str());
              sab++;
	    }

	    std::map<std::string, double>::iterator dab = gm->da->begin();
	    std::map<std::string, double>::iterator dae = gm->da->end();
	    while (dab != dae) {
	      std::pair<std::string, double> p = (*dab);
	      //printf("   da %s = %f\n", p.first.c_str(), p.second);
              dab++;
	    }

	    std::map<std::string, int>::iterator iab = gm->ia->begin();
	    std::map<std::string, int>::iterator iae = gm->ia->end();
	    while (iab != iae) {
	      std::pair<std::string, int> p = (*iab);
	      //printf("   ia %s = %d\n", p.first.c_str(), p.second);
              iab++;
	    }

	    //            printf("%3d: BISON group %s\n", line_number, $1);
	    library = g;
            $$ = g;
          }
        | NAME LPAREN string_list RPAREN  LBRACE  groupitems  RBRACE {
            Group  *g  = new Group($1, $3->values->at(0));
	    GrpMap *gm = $6;

            g->add(gm);

	    std::map<std::string, std::string>::iterator sab = gm->sa->begin();
	    std::map<std::string, std::string>::iterator sae = gm->sa->end();
	    while (sab != sae) {
	      std::pair<std::string, std::string> p = (*sab);
	      //printf("   sa %s = %s\n", p.first.c_str(), p.second.c_str());
              sab++;
	    }

	    std::map<std::string, double>::iterator dab = gm->da->begin();
	    std::map<std::string, double>::iterator dae = gm->da->end();
	    while (dab != dae) {
	      std::pair<std::string, double> p = (*dab);
	      //printf("   da %s = %f\n", p.first.c_str(), p.second);
              dab++;
	    }

	    std::map<std::string, int>::iterator iab = gm->ia->begin();
	    std::map<std::string, int>::iterator iae = gm->ia->end();
	    while (iab != iae) {
	      std::pair<std::string, int> p = (*iab);
	      //printf("   ia %s = %d\n", p.first.c_str(), p.second);
              iab++;
	    }

	    std::map<std::string, StrVector*>::iterator cab = gm->ca->begin();
	    std::map<std::string, StrVector*>::iterator cae = gm->ca->end();
	    while (cab != cae) {
	      std::pair<std::string, StrVector*> p = (*cab);

	      std::vector<std::string>::iterator sb = p.second->values->begin();
	      std::vector<std::string>::iterator se = p.second->values->end();
	      while (sb != se) {
		//printf("   ca %s = %s\n", p.first.c_str(), (*sb).c_str());
		sb++;
	      }
              cab++;
	    }

	    library = g;
            $$ = g;
	  //	    printf("%3d: BISON named group %s\n", line_number, $1); 
          }
      ;

groupitems: string_attribute {
              GrpMap *gm = new GrpMap();
	      gm->add($1);
	      $$ = gm;
	    }
          | float_attribute {
              GrpMap *gm = new GrpMap();
	      gm->add($1);
	      $$ = gm;
	    }
          | int_attribute {
              GrpMap *gm = new GrpMap();
	      gm->add($1);
	      $$ = gm;
	    }
          | cplx_attribute {
              GrpMap *gm = new GrpMap();
	      gm->add($1);
	      $$ = gm;
            }
          | group {
              GrpMap *gm = new GrpMap();
	      gm->add($1);
	      $$ = gm;
            }
          | groupitems string_attribute  {
              GrpMap *gm = $1;
	      gm->add($2);
	      $$ = gm;
            }
          | groupitems float_attribute  {
              GrpMap *gm = $1;
	      gm->add($2);
	      $$ = gm;
            }
          | groupitems int_attribute  {
              GrpMap *gm = $1;
	      gm->add($2);
	      $$ = gm;
            }
          | groupitems cplx_attribute  {
              GrpMap *gm = $1;
	      gm->add($2);
	      $$ = gm;
            }
          | groupitems group  {
              GrpMap *gm = $1;
	      gm->add($2);
	      $$ = gm;
            }
;

string_attribute:
       NAME COLON NAME SEMI
         { 
	   StrAttribute *a = new StrAttribute($1, $3);
	   $$ = a;
	 }
     | NAME COLON QSTRING SEMI
         {
 	   StrAttribute *a = new StrAttribute($1, $3);
	   $$ = a;
	 }
;

float_attribute:
     NAME COLON FLOAT SEMI
         { 
 	   DblAttribute *a = new DblAttribute($1, $3);
	   $$ = a;
	 }
;

int_attribute:
     NAME COLON INT SEMI
         { 
 	   IntAttribute *a = new IntAttribute($1, $3);
	   $$ = a;
	 }
;

cplx_attribute:
            NAME LPAREN string_list RPAREN {
              CmplxAttribute *a = new CmplxAttribute($1);
	      a->add($3);
	      $$ = a;
	      /* printf("%3d: INCORRECT BISON cplx_attribute %s\n", line_number, $1); */
	    }
          | NAME LPAREN string_list RPAREN SEMI {
              CmplxAttribute *a = new CmplxAttribute($1);
	      a->add($3);
	      $$ = a;
            }
;

string_list: NAME {
               StrVector *l = new StrVector();
	       l->push_back($1); 
	       $$ = l;
	     }
           | QSTRING {
               StrVector *l = new StrVector();
	       l->push_back($1); 
	       $$ = l;
             }
           | INT {
               char buf[32];
               sprintf(buf, "%d", $1);

               StrVector *l = new StrVector();
	       l->push_back(buf); 
	       $$ = l;
             }
           | FLOAT {
               char buf[32];
               sprintf(buf, "%f", $1);

               StrVector *l = new StrVector();
	       l->push_back(buf); 
	       $$ = l;
             }
           | string_list COMMA NAME {
               $1->push_back($3);
	       $$ = $1;
             }
           | string_list COMMA QSTRING  {
               $1->push_back($3);
	       $$ = $1;
             }
           | string_list COMMA INT  {
               char buf[32];
               sprintf(buf, "%d", $3);

               $1->push_back(buf);
	       $$ = $1;
             }
           | string_list COMMA FLOAT {
               char buf[32];
               sprintf(buf, "%f", $3);

               $1->push_back(buf);
	       $$ = $1;
             }
 ;

%%


main ()
{
  yyparse ();
  
  printf("*** %s (%s)\n", library->name.c_str(), library->id.c_str());
  
  std::vector<GrpMap*>::iterator gmb = library->values->begin();
  std::vector<GrpMap*>::iterator gme = library->values->end();

  std::map<std::string, std::string>::iterator dm = (*gmb)->sa->find("delay_model");
  printf("DIRECT LOOK UP DELAY MODEL %s = %s\n", (*dm).first.c_str(), (*dm).second.c_str());

  //  std::map<std::string, std::map<std::string, std::vector<Group*>* > * > *grp;
  while(gmb != gme) {

    std::map<std::string, std::string>::iterator sab = (*gmb)->sa->begin();
    std::map<std::string, std::string>::iterator sae = (*gmb)->sa->end();
    while (sab != sae) {
      std::pair<std::string, std::string> p = (*sab);
      printf("   sa %s = %s\n", p.first.c_str(), p.second.c_str());
      sab++;
    }
    
    std::map<std::string, std::map<std::string, std::vector<Group*>* > * >::iterator gb = (*gmb)->grp->begin();
    std::map<std::string, std::map<std::string, std::vector<Group*>* > * >::iterator ge = (*gmb)->grp->end();
    while (gb != ge) {
      
      std::map<std::string, std::vector<Group*>* >::iterator ngb = (*gb).second->begin();
      std::map<std::string, std::vector<Group*>* >::iterator nge = (*gb).second->end();
      while (ngb != nge) {
	printf("     %s (%s)\n", (*gb).first.c_str(), (*ngb).first.c_str());
	ngb++;
      }
      gb++;
    }
    
    gmb++;
  }
  
  //  std::map<std::string, std::string> *sa;

}

void yyerror(const char* errstr) {
	printf("Error: %s\n", errstr);
}
